<template>
    <div
        class="wh-100% overflow-hidden flex flex-col"
        style="border: 1px solid #ccc"
    >
        <Toolbar
            style="border-bottom: 1px solid #ccc"
            :editor="editorRef!"
            :defaultConfig="toolbarConfig"
            mode="simple"
        />
        <div class="flex-1 overflow-scroll">
            <Editor :defaultConfig="editorConfig" @onCreated="handleCreated" />
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { IEditorConfig, IToolbarConfig, IDomEditor } from "@wangeditor/editor";

type InsertFnType = (url: string, alt: string, href: string) => void;

// 存储图片ID与Base64的映射
const base64ImageMap = new Map();

// 编辑器实例
const editorRef = ref<IDomEditor | null>(null);

const editorConfig: Partial<IEditorConfig> = {
    placeholder: "请输入内容",
    MENU_CONF: {
        uploadImage: {
            // server: "http://localhost:3000/api/upload-img",
            fieldName: "file",
            maxFileSize: 10 * 1024 * 1024, // 10M,
            maxNumberOfFiles: 1, // 最多上传 1 张图片
            customUpload: async (file: any, insertFn: InsertFnType) => {
                try {
                    // 生成唯一图片ID
                    const imageId = `img_${Date.now()}_${Math.random()
                        .toString(36)
                        .substring(2)}`;

                    // 转换为Base64并预览
                    const reader = new FileReader();
                    const base64Url: string = await new Promise(
                        (resolve, reject) => {
                            reader.onload = () =>
                                resolve(reader.result as string);
                            reader.onerror = reject;
                            reader.readAsDataURL(file);
                        }
                    );

                    // 插入带自定义属性的图片（方便后续查找替换）
                    insertFn(base64Url, imageId, "#");

                    // 存储ID与Base64的映射
                    base64ImageMap.set(imageId, base64Url);
                } catch (err) {
                    window.NMessage.error("图片上传预览失败");
                }
            },
        },
    },
};

const toolbarConfig: Partial<IToolbarConfig> = {
    excludeKeys: ["fullScreen", "insertVideo"],
};

// 编辑器创建完成后触发
const handleCreated = (editor: IDomEditor) => {
    editor.disable();
    editorRef.value = editor;
};

// 启用编辑器
const enableEditor = (content: string) => {
    editorRef.value?.enable();
    editorRef.value?.setHtml(content);
};

// 禁用编辑器
const disableEditor = () => {
    editorRef.value?.clear();
    editorRef.value?.disable();
};

const replaceImage = async (content: string) => {
    // 提取所有带特定alt的图片
    const imageRegex = /<img[^>]+alt="(img_\d+_[a-z0-9]+)"[^>]*>/g;
    const imageMatches = content.match(imageRegex);

    if (!imageMatches) {
        return content;
    }

    let newContent = content;
    for (const imgTag of imageMatches) {
        // 提取alt中的图片ID
        const idMatch = imgTag.match(/alt="(img_\d+_[a-z0-9]+)"/);
        if (!idMatch) continue;

        const imageId = idMatch[1];
        const base64Url = base64ImageMap.get(imageId);

        if (!base64Url) continue;

        // 4. 上传到OSS
        // const ossUrl = await uploadToOSS(base64Url, imageId);

        // 5. 替换图片URL（保留alt和其他属性）
        // const newImgTag = imgTag.replace(/src="[^"]+"/, `src="${ossUrl}"`);

        // newContent = newContent.replace(imgTag, newImgTag);
    }
    return newContent;
};

// 保存内容
const handleSave = async (origin: string) => {
    if (!editorRef.value) {
        throw new Error("编辑器未创建");
    }
    if (origin === editorRef.value.getHtml()) {
        throw new Error("未作任何修改");
    }
    if (editorRef.value.isEmpty()) {
        throw new Error("内容不能为空");
    }

    // 获取编辑器内容
    const content = editorRef.value.getHtml();
    try {
        const newContent = await replaceImage(content);
        base64ImageMap.clear();
        return newContent || "";
    } catch (error) {
        throw new Error("上传图片失败");
    }
};

defineExpose({
    enableEditor,
    disableEditor,
    handleSave,
});
</script>

<style scoped></style>
